package com.levi.juc.common_class;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * CyclicBarrier  加法计数器
 * 累加到一定的数值后，才能执行某个任务
 *
 * CyclicBarrier 是另外一种多线程并发控制工具。
 *
 * 和 CountDownLatch 非常类似，它也可以实现线程间的计数等待，但它的功能比 CountDownLatch 更加复杂且强大。
 *
 * CyclicBarrier 可以理解为循环栅栏。
 *
 * 栅栏就是一种障碍物，比如，通常在私人宅邸的周围就可以围上一圈栅栏，阻止闲杂人等入内。
 *
 * 这里当然就是用来阻止线程继续执行，要求线程在栅栏外等待。
 *
 * 前面 Cyclic 意为循环，也就是说这个计数器可以反复使用。
 *
 * 比如，我们将计数器设置为 10 ，那么湊齐第一批 10 个线程后，计数器就会归零，接着凑齐下一批 10 个线程，这就是循环栅栏内在的含义。
 *
 * 举例  一个桌子 10个人吃饭，只有10个人全部到齐了 才能开始吃，否则都不能吃，这10个人吃完了，调用cyclicBarrier.await()方法再循环一圈，让另外10个人上来吃，依次循环
 * ————————————————
 */
public class CyclicBarrierTest {
    public static void main(String[] args) {
        //计数达到7才执行runable里面的run方法

//        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
//            System.out.println("召唤神龙");
//        });
//
//        for (int i = 1; i <= 14; i++) {
//            final int temp = i;
//            new Thread(() -> {
//                System.out.println("收集到了" + temp + "个龙珠");
//                try {
//                    cyclicBarrier.await();
//                } catch (InterruptedException | BrokenBarrierException e) {
//                    e.printStackTrace();
//                }
//            }).start();
//            if (i == 7) {
//                try {
//                    cyclicBarrier.await();
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        }


        CyclicBarrier c = new CyclicBarrier(7,()->{
            System.out.println("时机已到！！");
        });

        for (int i = 1; i <= 8; i++) {
            final int tem = i;
            new Thread(()->{
                try {
                    //5秒之后没有其他的线程进来则会抛异常
                    c.await(5, TimeUnit.SECONDS);
                    System.out.println("收集到" + tem + "个龙珠！");
                } catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
